package cn.matezk.lianlian.task;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.matezk.lianlian.beans.Constant;
import cn.matezk.lianlian.dao.DeviceDao;
import cn.matezk.lianlian.dao.NotifyRecordDao;
import cn.matezk.lianlian.dao.SecretKeyDao;
import cn.matezk.lianlian.dao.UserDao;
import cn.matezk.lianlian.framework.RedisMutexLock;
import cn.matezk.lianlian.model.Device;
import cn.matezk.lianlian.model.NotifyRecord;
import cn.matezk.lianlian.model.NotifyTemplate;
import cn.matezk.lianlian.model.SecretKey;
import cn.matezk.lianlian.utils.StringUtils;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.QuerySendDetailsRequest;
import com.aliyun.dysmsapi20170525.models.QuerySendDetailsResponse;
import com.aliyun.dysmsapi20170525.models.QuerySendDetailsResponseBody;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class SMSSyncTask {
    @Autowired
    private NotifyRecordDao notifyRecordDao;
    @Autowired
    private SecretKeyDao secretKeyDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private DeviceDao deviceDao;
    @Autowired
    private RedisMutexLock mutexLock;
    @Autowired
    private Client client;

    private static final String LOCK_KEY = "lock.sms";

    @XxlJob("smsSyncTask")
    public void execute() {
        if (!mutexLock.lock(LOCK_KEY,1000 * 60))    return;
        XxlJobHelper.log("同步短信发送状态任务开始执行");
        try {
            List<NotifyRecord> records = notifyRecordDao.selectWaitNotifyByMethod(NotifyTemplate.METHOD_SMS);
            if (ObjectUtil.isEmpty(records)) return;
            for (NotifyRecord record : records) {
                QuerySendDetailsRequest req = new QuerySendDetailsRequest();
                req.setBizId(record.getBizId());
                req.setPhoneNumber(record.getToUser());
                req.setSendDate(DateUtil.format(record.getNotifyTime(), DatePattern.PURE_DATE_PATTERN));
                req.setPageSize(1L);
                req.setCurrentPage(1L);
                try {
                    QuerySendDetailsResponse response = client.querySendDetails(req);
                    if (!response.getBody().getCode().equals("OK")
                            || response.getBody().getTotalCount().equals("0"))
                        continue;
                    QuerySendDetailsResponseBody.QuerySendDetailsResponseBodySmsSendDetailDTOs details = response.getBody().getSmsSendDetailDTOs();
                    for (QuerySendDetailsResponseBody.QuerySendDetailsResponseBodySmsSendDetailDTOsSmsSendDetailDTO item : details.getSmsSendDetailDTO()) {
                        if (item.getSendStatus().intValue() == 1)
                            continue;
                        String notifyLockKey = NotifyRecord.createLockKey(record.getBizId());
                        record.setErrorCode(StringUtils.sub(item.getErrCode(), 30));
                        record.setStatus(item.getSendStatus().intValue() == 3 ? NotifyRecord.STATUS_SUCCESS : NotifyRecord.STATUS_FAILED);
                        if (mutexLock.tryLock(notifyLockKey, 3)) {
                            try {
                                int count = notifyRecordDao.updateByBizId(record);
                                if (count > 0 && NotifyRecord.STATUS_FAILED.equals(item.getSendStatus())) {
                                    // 是否绑定APPKEY
                                    SecretKey secretKey = secretKeyDao.deviceMatch(record.getProductId(), record.getDeviceName());
                                    // 是否绑定了用户
                                    Long userId = ObjectUtil.isNull(secretKey) ? null : secretKey.getBindUser();
                                    String amountLockKey = Device.createLockKey(record.getDeviceId());
                                    if (ObjectUtil.isNotNull(userId)) {
                                        amountLockKey = String.format("lock.user.%d", userId);
                                    }
                                    if (mutexLock.tryLock(amountLockKey, 3)) {
                                        try {
                                            if (ObjectUtil.isNotNull(userId)) {
                                                // 退还到账户余额
                                                Integer amount = userDao.userAmount(userId);
                                                userDao.updateAmount(userId, amount + Constant.SMS_UNIT_PRICE);
                                            } else {
                                                // 退还到设备余额
                                                Device device = deviceDao.selectByPrimaryKey(record.getDeviceId());
                                                deviceDao.updateAmount(device.getDeviceId(), device.getAmount() + Constant.SMS_UNIT_PRICE);
                                            }
                                        } finally {
                                            mutexLock.unlock(amountLockKey);
                                        }
                                    }
                                }
                            } finally {
                                mutexLock.unlock(notifyLockKey);
                            }
                        }
                    }
                } catch (Exception e) {
                    XxlJobHelper.log(e);
                    continue;
                }
            }
        } catch (Exception e) {
            XxlJobHelper.log(e);
        } finally {
            XxlJobHelper.log("同步短信发送状态任务执行完毕");
            mutexLock.unlock(LOCK_KEY);
        }
    }
}
